import { TimerUtils } from "../../api/timer/TimerUtils";
import { E_BuyTimeLimitRefreshType } from "../defs/buy_times/E_BuyTimeLimitRefreshType";
import { E_TimeConfig } from "../defs/com/E_TimeConfig";
import { E_MsgCode } from "../defs/proto/E_MsgCode";
import { CDShop } from "../excel/CDShop";
import { CDShopGood } from "../excel/CDShopGood";
import { CEBuyTimes } from "../excel_extend/CEBuyTimes";
import { Player } from "../struct/Player";
import { Shop } from "../struct/Shop";
import { SDActivity } from "./SDActivity";
import { SDBuyTimeLimit } from "./SDBuyTimeLimit";
import { SDMission } from "./SDMission";
import { SDRandomEvent } from "./SDRandomEvent";
import { SDServer } from "./SDServer";


/**系统重置时间 */
const SYSTEM_RESET_TIME = E_TimeConfig.Hour * 5;


/**
 * 数据-商城
 */
export abstract class SDShop {

    /**不可购买时的参数 */
    public static shopGoodCannotSellParam: any = null;


    /**
     * 获取商店重置倒计时
     * @param player 
     * @param shopConfig 
     * @param nowTime 
     * @returns 
     */
    public static getShopRefreshCountDown(
        player: Player,
        shopConfig: number | CDShop,
        nowTime: number
    ): number {
        if (!(shopConfig instanceof CDShop)) {
            shopConfig = CDShop.getData(shopConfig || 0);
        }
        if (!shopConfig) {
            // return E_TimeConfig.Minute;  //目前每个商店都一样
        }

        const resetTime = TimerUtils.getDayZeroTime(nowTime) + SYSTEM_RESET_TIME;
        if (resetTime === nowTime) {
            return 1;      //相同的
        }
        else if (resetTime > nowTime) {
            return resetTime - nowTime;                            //还没到的用今天
        }
        else {
            return (resetTime + E_TimeConfig.Day) - nowTime;      //超过的就是明天了
        }
    }


    /**
     * 获取请求更新信息的延迟
     * @param player 
     * @param nowTime
     * @returns 0-不需要，< 0-马上，其他-延迟
     */
    public static getReqUpdateCountDown(
        player: Player,
        nowTime: number
    ): number {

        let countDown = E_TimeConfig.Month;

        //跨天更新
        {
            let daily = TimerUtils.getDayZeroTime(nowTime) + SYSTEM_RESET_TIME;
            if (nowTime >= daily) {
                daily += E_TimeConfig.Day;
            }
            countDown = daily - nowTime;
        }

        //各个商店的刷新自增
        {
            const vs = CDShop.datas.getValues();
            for (let i = 0, len = vs.length; i < len; i++) {
                const t = this.getFreeRefreshCountDown(player, vs[i], nowTime);
                if (t > 0 && countDown > t) {
                    countDown = t;
                }
            }
        }

        return countDown;
    }


    /**
     * 商城是否开放
     * @param player 
     * @param shopConfig 
     * @returns 0-是，其他-异常情况
     */
    public static checkShopOpenStatus(player: Player, shopConfig: number | CDShop): number {
        if (!(shopConfig instanceof CDShop)) {
            shopConfig = CDShop.getData(shopConfig || 0);
        }
        if (!shopConfig) {
            return E_MsgCode.ShopConfigNotFind;
        }

        if (shopConfig.activityType > 0) {
            if (!SDActivity.isOpen(player, shopConfig.activityType)) {
                return E_MsgCode.ActiveUnOpen;
            }
        }

        //特殊处理随机事件商店
        if (!SDRandomEvent.isRandomEventShopOpen(player, shopConfig.id)) {
            return E_MsgCode.RandomEventShopUnOpen;
        }

        return 0;
    }


    /**
     * 数据需要清零
     * @param player 
     * @param firstTime 
     * @param nowTime 
     * @param rt 
     * @returns 
     */
    public static isNeedClearSell(player: Player, firstTime: number, nowTime: number, rt: E_BuyTimeLimitRefreshType): boolean {
        switch (rt) {
            case E_BuyTimeLimitRefreshType.Forever:
                //永久
                break;

            case E_BuyTimeLimitRefreshType.Daily:
                if (TimerUtils.isDailyTrigger(SYSTEM_RESET_TIME, firstTime, nowTime)) {
                    return true;
                }
                break;

            case E_BuyTimeLimitRefreshType.Weekly:
                if (TimerUtils.isWeeklyTrigger(SYSTEM_RESET_TIME, firstTime, SDServer.getServerCreateTime(player), nowTime)) {
                    return true;
                }
                break;

            case E_BuyTimeLimitRefreshType.Monthly:
                if (TimerUtils.isMonthlyTrigger(SYSTEM_RESET_TIME, firstTime, SDServer.getServerCreateTime(player), nowTime)) {
                    return true;
                }
                break;

            case E_BuyTimeLimitRefreshType.Activity:
                {
                    //TODO 需要做判定
                    return false;
                }
                break;

            default:
                console.warn('没有处理商店出售限制类型：' + rt);
                break;
        }

        return false;
    }


    /**
     * 商品可购买状态
     * @param player 
     * @param shopConfig 
     * @param goodConfig 
     * @param buyTimes 
     * @param checkItemCost 
     * @param nowTime 
     * @returns 
     */
    public static checkShopGoodCanSellStatus(
        player: Player,
        shopConfig: number | CDShop,
        goodConfig: number | CDShopGood,
        buyTimes: number,
        checkItemCost: boolean,
        nowTime: number
    ): number {

        if (!(goodConfig instanceof CDShopGood)) {
            goodConfig = CDShopGood.getData(goodConfig || 0);
        }
        if (!goodConfig) {
            return E_MsgCode.ShopGoodConfigNotFind;
        }

        //等级
        if (goodConfig.unlockLevel > player.playerInfo.level) {
            this.shopGoodCannotSellParam = goodConfig.unlockLevel;
            return E_MsgCode.PlayerLevelUnFit;
        }

        //活动
        if (goodConfig.activityID > 0) {
            if (!SDActivity.isOpen(player, goodConfig.activityID)) {
                this.shopGoodCannotSellParam = goodConfig.activityID;
                return E_MsgCode.ActiveUnOpen;
            }
        }

        //限制
        if (goodConfig.limitId > 0) {
            const r = SDBuyTimeLimit.checkBuyStatus(player, goodConfig.limitId, buyTimes);
            if (0 !== r) {
                this.shopGoodCannotSellParam = SDBuyTimeLimit.canNotBuyParam;
                return r;
            }
        }
        else {
            //没有写限制的，默认 1.随机商店限制一次，2.固定商店不限制
            const shop = this.getShopByConfigId(player, shopConfig, false);
            if (!shop) {
                return E_MsgCode.ShopNotExist;
            }

            const shopItem = shop.getItem(goodConfig.id);
            if (shopItem.buyTimes > 0) {
                const shopConfig = CDShop.getData(goodConfig.shopId);
                if (shopConfig.goodsNum > 0) {
                    this.shopGoodCannotSellParam = shopItem.buyTimes;
                    return E_MsgCode.ShopSellTimesLimit;
                }
            }
        }

        //任务
        if (goodConfig.missonID > 0) {
            if (!SDMission.isMissionOpen(player, goodConfig.missonID, nowTime)) {
                this.shopGoodCannotSellParam = goodConfig.missonID;
                return E_MsgCode.MissionNotOpen;
            }
        }

        //vip
        if (goodConfig.reqVip > player.vip.level) {
            this.shopGoodCannotSellParam = goodConfig.reqVip;
            return E_MsgCode.PlayerVipLevelUnFit;
        }

        //道具消耗
        if (checkItemCost) {
            if (goodConfig.costItemId !== 0) {
                const costItemID = goodConfig.costItemId;
                const costItemNum = goodConfig.costItemNum * buyTimes;
                const count = player.getItemNum(costItemID);
                if (count < costItemNum) {
                    this.shopGoodCannotSellParam = [costItemID, count, costItemNum];
                    return E_MsgCode.ItemNotEnough;
                }
            }
            if (goodConfig.costItemId_2 !== 0) {
                const costItemID = goodConfig.costItemId_2;
                const costItemNum = goodConfig.costItemNum_2 * buyTimes;
                const count = player.getItemNum(costItemID);
                if (count < costItemNum) {
                    this.shopGoodCannotSellParam = [costItemID, count, costItemNum];
                    return E_MsgCode.ItemNotEnough;
                }
            }
        }

        this.shopGoodCannotSellParam = 0;

        return 0;
    }


    /**
     * 获取指定商店
     * @param player 
     * @param shopConfig 
     * @param checkOpen
     * @returns 
     */
    public static getShopByConfigId(
        player: Player,
        shopConfig: number | CDShop,
        checkOpen: boolean
    ): Shop {

        if (!(shopConfig instanceof CDShop)) {
            shopConfig = CDShop.getData(shopConfig || 0);
        }
        if (checkOpen && 0 !== this.checkShopOpenStatus(player, shopConfig)) {
            return null;
        }

        if (shopConfig.goodsNum <= 0) {
            //固定的，TODO
            const shop = player.shopManager.getShop(shopConfig.id);
            return shop;
        }
        else {
            //随机商店
            const shop = player.shopManager.getShop(shopConfig.id);
            return shop;
        }
    }


    /**
     * 获取商店免费刷新时间倒计时
     * @param player 
     * @param shopConfig 
     * @param nowTime
     * @returns <=0-无
     */
    public static getFreeRefreshCountDown(
        player: Player,
        shopConfig: number | CDShop,
        nowTime: number
    ): number {

        if (!(shopConfig instanceof CDShop)) {
            shopConfig = CDShop.getData(shopConfig || 0);
        }
        const shop = SDShop.getShopByConfigId(player, shopConfig, true);
        if (!shop) {
            return 0;
        }

        if (shopConfig.freeRefreshTime <= 0) {
            return 0;
        }

        if (shopConfig.refreshMaxNum > 0
            && shopConfig.initFreeRefreshNum + shop.freeRefreshAutoAdd >= shopConfig.refreshMaxNum + shop.freeRefreshUse) {
            return 0;       //已自增到最大数量
        }

        const duraction = E_TimeConfig.Second * shopConfig.freeRefreshTime;
        const pass = nowTime - shop.freeRefreshAutoAddStartTime;
        if (pass >= duraction) {
            return 1;       //尽量少的时间
        }

        return duraction - pass;
    }


    /**
     * 获取免费刷新次数
     * @param player 
     * @param shopConfig 
     * @param nowTime 
     * @returns 
     */
    public static getRefreshFreeNum(
        player: Player,
        shopConfig: number | CDShop,
        nowTime: number
    ): number {

        if (!(shopConfig instanceof CDShop)) {
            shopConfig = CDShop.getData(shopConfig || 0);
        }

        const shop = SDShop.getShopByConfigId(player, shopConfig, true);
        if (shop) {
            let count = shopConfig.initFreeRefreshNum;
            count += shop.freeRefreshAutoAdd;                           //已自增

            // 预期自增
            if (shopConfig.freeRefreshTime > 0 && shopConfig.refreshMaxNum > 0) {
                const pass = nowTime - shop.freeRefreshAutoAddStartTime;
                const duraction = E_TimeConfig.Second * shopConfig.freeRefreshTime;
                const prevAdd = Math.floor(pass / duraction);
                if (prevAdd > 0) {
                    count += prevAdd;
                    //限制最大数量
                    if (count > shopConfig.refreshMaxNum + shop.freeRefreshUse) {
                        count = shopConfig.refreshMaxNum + shop.freeRefreshUse;
                    }
                }
            }

            if (shop.freeRefreshUse < count) {
                return count - shop.freeRefreshUse;
            }
        }

        return 0;
    }


    /**
     * 可以免费刷新
     * @param player 
     * @param shopConfig 
     * @param nowTime 
     * @returns 
     */
    public static canRefreshFree(
        player: Player,
        shopConfig: number | CDShop,
        nowTime: number
    ): boolean {
        const v = this.getRefreshFreeNum(player, shopConfig, nowTime);
        return v > 0;
    }


    /**
     * 可以消耗刷新
     * @param player 
     * @param shopConfig 
     * @param checkCostItem 检测道具是否充足
     */
    public static canRefreshCost(player: Player, shopConfig: number | CDShop, checkCostItem = false): boolean {
        if (!(shopConfig instanceof CDShop)) {
            shopConfig = CDShop.getData(shopConfig || 0);
        }

        const shop = SDShop.getShopByConfigId(player, shopConfig, true);
        if (!shop) {
            return false;
        }

        //达到刷新上限
        const costItemNum = CEBuyTimes.getShopRefreshCostNum(shop.costRefreshUse);
        if (costItemNum < 0) {
            return false;
        }

        //道具不足
        if (checkCostItem) {
            const costItemID = shopConfig.costItemId;
            const count = player.getItemNum(costItemID);
            if (count < costItemNum) {
                return false;
            }
        }

        return true;
    }



}
